#include "Rp.h"
#include "stm32f10x.h"  

uint16_t rp_buf[4] = {0,0,0,0};

void init_adc1_dma(void){
    
    DMA_InitTypeDef dma_init;

    // 转移adc数据到内存时：adc_DR 寄存器为源地址
    dma_init.DMA_DIR = DMA_DIR_PeripheralSRC;
    
    /**
    
    分解说明
        ADC1->DR：通过 ADC1 结构体指针访问其数据寄存器 DR

        &(ADC1->DR)：获取 DR 寄存器的内存地址（指针）

        (uint32_t)：将指针强制转换为 32 位无符号整数（物理地址）

        DMA_PeripheralBaseAddr：DMA 外设端数据源的起始地址
    
    1、为什么不能直接写 ADC1->DR？
        ADC1->DR 是寄存器内容（数据值），不是地址

        DMA 需要的是数据源的存放地址，而不是数据本身

        & 操作符获取的是存放数据的寄存器位置
    
    2、为什么需要这样写？
        DMA 需要知道外设数据寄存器的物理内存地址

        ADC1->DR 是结构体访问方式，通过 & 取地址操作符获取其地址

        标准外设库中寄存器映射为结构体，但 DMA 配置需要原始地址值
    */
    dma_init.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);//ADC1->DR;
    dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    dma_init.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
    
    dma_init.DMA_MemoryBaseAddr = (uint32_t)rp_buf;
    dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
    
    dma_init.DMA_Priority = DMA_Priority_Low;
    dma_init.DMA_BufferSize=4;
    dma_init.DMA_M2M = DMA_M2M_Disable;
    
    //重点： 不能开启循环模式，否则会重复不停地往串口发送数据
    dma_init.DMA_Mode = DMA_Mode_Circular;
    
    DMA_Init(DMA1_Channel1,&dma_init);
}

void init_dma_irq(void){
    
    DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
    
    
    NVIC_InitTypeDef nvic;
    nvic.NVIC_IRQChannel=DMA1_Channel1_IRQn;
    nvic.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&nvic);
}

void initRp(void){

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);

    GPIO_Init(GPIOA,&(GPIO_InitTypeDef){
        
        .GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 |GPIO_Pin_4 | GPIO_Pin_5,
        .GPIO_Mode = GPIO_Mode_AIN,      // 配置为模拟量输入
        .GPIO_Speed=GPIO_Speed_50MHz
    });
    
    
     ADC_Init(ADC1, &(ADC_InitTypeDef){
         .ADC_Mode = ADC_Mode_Independent,
         .ADC_ScanConvMode=ENABLE,
         .ADC_ContinuousConvMode=ENABLE,
         //软件触发
         .ADC_ExternalTrigConv=ADC_ExternalTrigConv_None,
         .ADC_DataAlign=ADC_DataAlign_Right,
         .ADC_NbrOfChannel=4
     });
    
    // 把gpio_2 绑定到 regular group sequencer 1 中
    ADC_RegularChannelConfig(ADC1,ADC_Channel_2,1,ADC_SampleTime_55Cycles5); 
    ADC_RegularChannelConfig(ADC1,ADC_Channel_3,2,ADC_SampleTime_55Cycles5); 
    ADC_RegularChannelConfig(ADC1,ADC_Channel_4,3,ADC_SampleTime_55Cycles5); 
    ADC_RegularChannelConfig(ADC1,ADC_Channel_5,4,ADC_SampleTime_55Cycles5); 
 
    init_adc1_dma(); 
    
    ADC_DMACmd(ADC1,ENABLE);
    
   
    
    ADC_Cmd(ADC1,ENABLE);
     
     // 校准 ADC
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
    

    DMA_Cmd(DMA1_Channel1,ENABLE);
    
    //init_dma_irq();
    
    // 软件触发开始转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

uint16_t get_rp_val(int index){
    if(index>3){
        return 0;
    }
    return rp_buf[index] & 0xfff;
}
